/*
 * CreatureAIData.cpp
 *
 *  Created on: 2017��3��20��
 *      Author: gaoyi
 */


#include "CreatureAIData.h"

#include "behaviac/behaviac.h"
#include "Character/newAI/AiLogicUtility.h"
#include "Character/Creature.h"
#include "Common/Event/Event.h"
#include "Character/SkillPart.h"
#include "Skill/SkillMgr.h"
#include "Common/TableData/AiAiCfg.h"
#include "Common/TableData/SkillSkillCfg.h"
#include "base/core/utility.h"
#include "Character/monster/Monster.h"
#include "CreatureCommonAI.h"
#include "Character/drop/DropMgr.h"
#include "Effect/EffectMgr.h"


void AiData_ForPatrolRandomPos::Clear()
{
	m_targetPos.x = 0.0f;
	m_targetPos.y = 0.0f;
	m_targetPos.z = 0.0f;
}

bool	AiData_ForPatrolRandomPos::IsSetRandomTargetPos()
{
	if (m_targetPos == Point3<float>())
	{
		return true;
	}
	return false;
}

void	AiData_ForPatrolRandomPos::SetRandomTargetPos()
{
	//��ֹ�����0��
	Point3<float> randomPos = AiLogicUtility::GetRandomPosInCircle(m_pMaster->GetMapId(), m_homePos, m_activeRange / 1000.0f);
	if (randomPos == Point3<float>())
	{
		randomPos = m_homePos;
	}
	m_targetPos = randomPos;
}

void  AiData_ForPatrolRandomPos::SetTargetPos(const Point3<float>& pos)
{
	m_targetPos = pos;
}

bool AiData_ForPatrolRandomPos::IsReachTargetPos()
{
	return point2LengthSquare(m_targetPos, m_pMaster->GetPos()) < 0.1;
}

void AiData_ForPatrolRandomPos::ReachTargetPos()
{
	m_lastTargetPos = m_targetPos;
	SetRandomTargetPos();
}

bool AiData_ForPatrolRandomPos::MoveToTargetPos()
{
	return m_pMaster->MoveTo(m_targetPos);
}

void AiData_ForPatrolPath::Clear()
{
	m_moveToTarget = true;
	m_nextPatrolPathIndex = 0;
	m_isFinish = false;
	m_patroType = 0;
}

Point3<float> AiData_ForPatrolPath::GetNeastPos(const Point3<float>& pos)
{
	size_t index = 0;
	float minLength = 1000000.0f;
	for (size_t i = 0; i < m_patrolPath.size(); i++)
	{
		float length = point2LengthSquare(m_patrolPath[i], pos);
		if (length < minLength)
		{
			minLength = length;
			index = i;
		}
	}

	m_nextPatrolPathIndex = index;
	return m_patrolPath[index];
}

void AiData_ForPatrolPath::AddPatrolPath(const std::vector<Point3<float> >& vecPos, int8_t patroType)
{
	m_patroType = patroType;
	m_patrolPath.clear();
	m_patrolPath.assign(vecPos.begin(), vecPos.end());
	m_isFinish = false;
	m_moveToTarget = true;
	m_nextPatrolPathIndex = 0;
}

bool AiData_ForPatrolPath::IsReachNextPatrolPath()
{
	if (m_nextPatrolPathIndex >= m_patrolPath.size())
	{
		m_nextPatrolPathIndex = 0;
	}

	return point2LengthSquare(m_patrolPath[m_nextPatrolPathIndex], m_pMaster->GetPos()) < 0.1;
}

bool AiData_ForPatrolPath::MoveToNextPatrolPath()
{
	if (m_nextPatrolPathIndex >= m_patrolPath.size())
	{
		m_nextPatrolPathIndex = 0;
	}

	return m_pMaster->MoveTo(m_patrolPath[m_nextPatrolPathIndex]);
}

float AiData_ForPatrolPath::GetDictToNextPatrolPath()
{
	if (m_nextPatrolPathIndex >= m_patrolPath.size())
	{
		return 0.0f;
	}

	return point2Length(m_pMaster->GetPos(), m_patrolPath[m_nextPatrolPathIndex]);
}

void AiData_ForPatrolPath::SetNextPatrolPath()
{
	if (m_patroType == ENUM_MONSTER_PATROL_TYPE_ROUND_TRIP)
	{
		//std::cout << m_nextPatrolPathIndex << "------------->";
		if (m_moveToTarget)
		{
			m_nextPatrolPathIndex++;
			if (m_nextPatrolPathIndex >= m_patrolPath.size())
			{
				m_moveToTarget = false;
				m_nextPatrolPathIndex = m_patrolPath.size() - 1;
			}

		}
		else
		{
			if (m_nextPatrolPathIndex <= 0)
			{
				m_moveToTarget = true;
				m_nextPatrolPathIndex = 0;
			}
			else
			{
				m_nextPatrolPathIndex--;
			}

		}
		//std::cout << m_nextPatrolPathIndex << std::endl;
	}
	else if (m_patroType == ENUM_MONSTER_PATROL_TYPE_LOOP_TRIP)
	{
		m_nextPatrolPathIndex++;
		if (m_nextPatrolPathIndex >= m_patrolPath.size())
		{
			if(m_moveToTarget)
			{
				m_moveToTarget = false;
			}
			else if (m_moveToTarget == false)
			{
				m_moveToTarget = true;
			}

			m_nextPatrolPathIndex = 0;
		}
	}
	else
	{
		//Point3<float> pos = m_pMaster->GetPos();
		//LogDebugFmtPrint("[logic] AiData_ForPatrolPath ----- cid:%u,  monsid:%u ,index:%u [%f,%f,%f] ", m_pMaster->GetCid(), m_pMaster->GetConfigId(), m_nextPatrolPathIndex, pos.x, pos.y, pos.z);
		m_nextPatrolPathIndex++;
		if (m_nextPatrolPathIndex >= m_patrolPath.size())
		{
			m_nextPatrolPathIndex = m_patrolPath.size() - 1;
			m_isFinish = true;
		}
	}
}

Point3<float> AiData_ForPatrolPath::GetTargetPos()
{
	if (m_nextPatrolPathIndex >= m_patrolPath.size())
	{
		m_nextPatrolPathIndex = 0;
	}
	//Point3<float> pos = m_pMaster->GetPos();
	//LogDebugFmtPrint("[logic] AiData_ForPatrolPath--GetTargetPos ----- cid:%u,  monsid:%u ,index:%u [%f,%f,%f] ", m_pMaster->GetCid(), m_pMaster->GetConfigId(), m_nextPatrolPathIndex, pos.x, pos.y, pos.z);

	return m_patrolPath[m_nextPatrolPathIndex];
}

void AiData_ForHateList::ClearDeadAndInvisible()
{
	for (auto it = m_hateList.begin(); it != m_hateList.end();)
	{
		Scene* pScene = m_pMaster->GetScene();
		if (pScene)
		{
			Creature* pCreature = pScene->GetCreature(it->m_hateTargetCid);
			if (pCreature == nullptr)
			{
				it = m_hateList.erase(it);
				continue;
			}

			if (pCreature->IsDead() || m_pMaster->ViewFliter(pCreature, 0) || m_pMaster->IsFriendSide(pCreature) || pCreature->GetScene() != m_pMaster->GetScene())
			{
				it = m_hateList.erase(it);
				continue;
			}

			if (pCreature->HasBuffState(CREATURE_BUFF_STATE_INVISIBLE) && !m_pMaster->HasBuffState(CREATURE_BUFF_STATE_SEEINVISIBLE))
			{
				it = m_hateList.erase(it);
				continue;
			}
		}
		it++;
	}
}

bool AiData_ForHateList::IsExistHateTarget(CharIDType targetCid)
{
	for (auto it = m_hateList.begin(); it != m_hateList.end(); it++)
	{
		if (it->m_hateTargetCid == targetCid)
		{
			return true;
		}
	}
	return false;
}

void AiData_ForHateList::AddHateTarget(CharIDType targetCid, int32_t hateValue, uint32_t damageValue)
{
	m_pMaster->GetAiData()->SetAiEnable(true);
	for (auto it = m_hateList.begin(); it != m_hateList.end(); it++)
	{
		if (it->m_hateTargetCid == targetCid)
		{
			it->m_damageValue += damageValue;
			it->m_hateValue += hateValue;
			return;
		}
	}

	if (hateValue < 0)
	{
		return;
	}

	HateTargetData data;
	data.m_hateTargetCid = targetCid;
	data.m_hateTime = g_GetGlobalServerTime()->Tick();
	data.m_hateValue = 5 + hateValue;
	data.m_damageValue = damageValue;

	m_hateList.push_back(data);
}

void AiData_ForHateList::RemoveHateTarget(CharIDType targetCid)
{
	for (HateTargetList::iterator it = m_hateList.begin(); it != m_hateList.end(); it++)
	{
		if (it->m_hateTargetCid == targetCid)
		{
			m_hateList.erase(it);
			return;
		}
	}
}

void AiData_ForHateList::SortHateList()
{
	ClearDeadAndInvisible();
	m_hateList.sort();
}

void AiData_ForPursuitTarget::Clear()
{
	m_targetPos.x = 0.0f;
	m_targetPos.y = 0.0f;
	m_targetPos.z = 0.0f;
	m_targetSrcPos.x = 0.0f;
	m_targetSrcPos.y = 0.0f;
	m_targetSrcPos.z = 0.0f;
	m_changeTargetPosTime = 0;
	m_pursuitSkillId = 0;
}

bool AiData_ForPursuitTarget::IsReach()
{
	if (m_targetPos == Point3<float>()) return false;
	return point2LengthSquare(m_targetPos, m_pMaster->GetPos()) < 0.1;
}

bool AiData_ForPursuitTarget::IsSkillChange(uint32_t skillId)
{
	return m_pursuitSkillId != skillId;
}

//���˱Ƚ�׷��Ŀ���λ���Ƿ����
bool AiData_ForPursuitTarget::IsChange(const Point3<float>& srcPos)
{
	return point2LengthSquare(m_targetSrcPos,srcPos) > 0.1;
}

void AiData_ForHPState::Clear()
{
	allTrigger = false;
	for (int i = 0; i < (int)vecState.size(); i++)
	{
		vecState[i].hpTrigger = false;
	}
}


void AiData_ForHPState::HandleStateSkill(int state)
{
	std::vector<int> addSkill;
	std::vector<int> removeSkill;
	CommonApi::SplitStrToVecInt(vecState[state].info.AddSkills, ",", &addSkill);
	CommonApi::SplitStrToVecInt(vecState[state].info.RemoveSkills, ",", &removeSkill);

	if (vecState[state].hasDrop && vecState[state].info.Drop > 0)
	{
		vecState[state].hasDrop = false;
		SDropSourcePram source;
		g_GetDropMgr()->OnMonsHpDrop(m_pMaster->GetSceneId(), vecState[state].info.Drop, m_pMaster->GetPos(), m_pMaster->GetConfigId(), m_pMaster->GetAttr(C_LEVEL), source);
	}

	if (vecState[state].info.Trigger > 0)
	{
		//触发出身效果
		g_GetEffectMgr()->OnEffect(m_pMaster, vecState[state].info.Trigger);
	}

	SkillPart* pSkillPart = dynamic_cast<SkillPart*>(m_pMaster->GetPart(PART_SKILL));
	if (pSkillPart)
	{
		if (addSkill.size() > 0 && addSkill.size() % 3 == 0)
		{
			for (size_t i = 0; i < addSkill.size(); i += 3)
			{
				int skillId = addSkill[i];
				int priority = addSkill[i + 1];
				int time = addSkill[i+2];

				if (g_GetSkillSkillCfgTable()->GetSkillSkillCfgInfo(skillId) != nullptr)
				{
					pSkillPart->AddSkill(skillId, 1, 0, priority,true,false);
					stSkillInfo* pSkillInfo = pSkillPart->GetSkillInfo(skillId);
					if (pSkillInfo)
					{
						pSkillInfo->_cdTimeStamps = Time::Now().UnixMSec() - pSkillInfo->_pSkillmeta->cd + time;
					}
				}
			}
		}
	}
}

//统一处理AI血触发条件
void AiData_ForHPState::HandleTriggerHpState()
{
	for(int state = 0; state < (int)vecState.size(); state++)
	{
		if (vecState[state].hpTrigger == false)
		{
			int32_t curHp = m_pMaster->GetAttr(C_HP);
			int32_t maxHp = m_pMaster->GetAttr(C_MAX_HP);

			float per = (float)curHp / (float)maxHp;
			if (per * 1000 <= vecState[state].info.Percentage)
			{
				vecState[state].hpTrigger = true;
				ComputeAllTrigger();

				HandleStateSkill(state);
			}
			break;
		}
	}
}

void AiData_ForHPState::ComputeAllTrigger()
{
	for(int i = 0; i < (int)vecState.size(); i++)
	{
		if (vecState[i].hpTrigger == false)
		{
			return;
		}
	}
	allTrigger = true;
}

bool AiData_ForHPState::IsHpStateNeedTrigger(int state)
{
	int32_t curHp = m_pMaster->GetAttr(C_HP);
	int32_t maxHp = m_pMaster->GetAttr(C_MAX_HP);

	if (state >= 0 && state < (int)vecState.size())
	{
		int32_t curHpPeriod = curHp * 1000 / maxHp;
		if (curHpPeriod <= vecState[state].info.Percentage)
		{
			return true;
		}
	}

	return false;
}

bool AiData_ForHPState::HasHpStateNoTrigger()
{
	return allTrigger == false;
}

bool AiData_ForHPState::IsHpStateNoTrigger(int state)
{
	if (state >= 0 && state < (int)vecState.size())
	{
		return vecState[state].hpTrigger == false;
	}
	return false;
}

void AiData_ForHPState::TriggerHpState(int state)
{
}
